﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace CC.Yacht.Windows.Forms
{
    public partial class GamePanel : UserControl
    {
        public GamePanel()
        {
            InitializeComponent();
            _IsInitialized = true;
        }

        #region Private Fields
        private User _CurrentUser;
        private readonly bool _IsInitialized;
        #endregion

        #region Public Events
        public event EventHandler<DiceChangedEventArgs> DiceChanged;
        public event EventHandler Rolling;
        public event EventHandler<ScoreChangedEventArgs> ScoreChanged;
        public event EventHandler<SendMessageEventArgs> SendingMessage;
        public event EventHandler Starting;
        #endregion

        #region Public Properties
        public Guid GameId { get; set; }

        /*
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Size MaximumSize
        {
            get { return base.MinimumSize; }
            set
            {
                if (!_IsInitialized)
                {
                    base.MaximumSize = value;
                }
            }
        }
        */

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Size MinimumSize
        {
            get { return base.MinimumSize; }
            set
            {
                if (!_IsInitialized)
                {
                    base.MinimumSize = value;
                }
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Size Size
        {
            get { return base.Size; }
            set
            {
                if (!_IsInitialized)
                {
                    base.Size = value;
                }
            }
        }

        public User User { get; set; }
        #endregion

        #region Private Event Handlers
        private void _ChatPanel_SendingMessage(object sender, SendMessageEventArgs e)
        {
            OnSendingMessage(e);
        }

        private void _GameTablePanel_DiceChanged(object sender, DiceChangedEventArgs e)
        {
            if (User.Equals(_CurrentUser))
            {
                OnDiceChanged(e);
            }
        }

        private void _GameTablePanel_Rolling(object sender, EventArgs e)
        {
            OnRolling();
        }

        private void _GameTablePanel_Starting(object sender, EventArgs e)
        {
            OnStarting();
        }

        // ReSharper disable InconsistentNaming
        private void ScorecardTabPage_Changed(object sender, ScoreChangedEventArgs e)
        // ReSharper restore InconsistentNaming
        {
            if (User.Equals(_CurrentUser))
            {
                OnScoreChanged(e);
            }
        }
        #endregion

        #region Private Methods
        private void AddScorecard(User user)
        {
            if (!_TabControlScorecards.TabPages.ContainsKey(user.UserId.ToString()))
            {
                ScorecardTabPage scorecardTabPage = new ScorecardTabPage(user);
                _TabControlScorecards.TabPages.Add(scorecardTabPage);

                if (User.Equals(user))
                {
                    scorecardTabPage.Changed += ScorecardTabPage_Changed;
                }

                _ChatPanel.AddAction(user.Username + " joined");
            }
        }

        private void RemoveScorecard(User user)
        {
            if (user != null && _TabControlScorecards.TabPages.ContainsKey(user.UserId.ToString()))
            {
                _TabControlScorecards.TabPages.RemoveByKey(user.UserId.ToString());
                _ChatPanel.AddAction(user.Username + " left");
            }
        }
        #endregion

        #region Protected Methods
        protected void OnDiceChanged(DiceChangedEventArgs eventArgs)
        {
            if (DiceChanged != null)
            {
                DiceChanged(this, eventArgs);
            }
        }

        protected void OnRolling()
        {
            if (Rolling != null)
            {
                Rolling(this, EventArgs.Empty);
            }
        }

        protected void OnScoreChanged(ScoreChangedEventArgs eventArgs)
        {
            if (ScoreChanged != null)
            {
                ScoreChanged(this, eventArgs);
            }
        }

        protected void OnSendingMessage(SendMessageEventArgs eventArgs)
        {
            if (SendingMessage != null)
            {
                SendingMessage(this, eventArgs);
            }
        }

        protected void OnStarting()
        {
            if (Starting != null)
            {
                Starting(this, EventArgs.Empty);
            }
        }
        #endregion

        #region Public Methods
        public void GameOver(User winner)
        {
            _GameTablePanel.GameOver(winner);
        }

        public void MessageReceived(User user, string message)
        {
            _ChatPanel.AddMessage(user, message);
        }

        public void Reset()
        {
            //TODO: Make sure this is hitting everything...
            while (_TabControlScorecards.TabPages.Count > 0)
            {
                ScorecardTabPage scorecardTabPage = _TabControlScorecards.TabPages[0] as ScorecardTabPage;

                if (scorecardTabPage != null)
                {
                    RemoveScorecard(scorecardTabPage.User);
                }
            }

            _ChatPanel.Clear();
        }

        public void Rolled(Dice dice)
        {
            _GameTablePanel.Rolled(dice);
        }

        public void SetGameState(GameState gameState)
        {
            // Clear out users that have left...
            for (int i = _TabControlScorecards.TabPages.Count - 1; i >= 0; i--)
            {
                ScorecardTabPage scorecardTabPage = _TabControlScorecards.TabPages[i] as ScorecardTabPage;

                if (scorecardTabPage != null)
                {
                    if (!gameState.Players.Contains(scorecardTabPage.User))
                    {
                        RemoveScorecard(scorecardTabPage.User);
                    }
                }
                else
                {
                    _TabControlScorecards.TabPages.RemoveAt(i);  
                }
            }

            // Add users that have joined...
            for (int i = 0; i < gameState.Players.Count; i++)
            {
                AddScorecard(gameState.Players[i]);
            }

            // Update dice...
            _GameTablePanel.UpdateDice(gameState.Dice);

            // Update scores
            foreach (KeyValuePair<long, Scorecard> keyValuePair in gameState.Scorecards)
            {
                Scorecard scorecard = keyValuePair.Value;

                if (_TabControlScorecards.TabPages.ContainsKey(scorecard.User.UserId.ToString()))
                {
                    ScorecardTabPage scorecardTabPage = _TabControlScorecards.TabPages[scorecard.User.UserId.ToString()] as ScorecardTabPage;

                    if (scorecardTabPage != null)
                    {
                        scorecardTabPage.ClearDice();
                        scorecardTabPage.UpdateScore(scorecard);
                    }
                }
                else
                {
                    throw new InvalidOperationException("A Scorecard exists but a corresponding User does not!");
                }
            }

            if (_CurrentUser != gameState.CurrentUser)
            {
                _CurrentUser = gameState.CurrentUser;
                _TabControlScorecards.SelectTab(_CurrentUser.UserId.ToString());
            }

            if (User.Equals(_CurrentUser))
            {
                _GameTablePanel.CanLock = true;
                _GameTablePanel.CanRoll = gameState.Dice.CanRoll;

                if (_TabControlScorecards.TabPages.ContainsKey(User.UserId.ToString()))
                {
                    ScorecardTabPage scorecardTabPage = _TabControlScorecards.TabPages[User.UserId.ToString()] as ScorecardTabPage;

                    if (scorecardTabPage != null)
                    {
                        scorecardTabPage.UpdateDice(gameState.Dice);
                    }
                }
            }
            else
            {
                _GameTablePanel.CanLock = false;
                _GameTablePanel.CanRoll = false;
            }

            if (gameState.IsStarted)
            {
                _GameTablePanel.StopFireworks();
            }

            _GameTablePanel.CanStart = (!gameState.IsStarted && User.Equals(gameState.Owner));
        }
        #endregion
    }
}
